package cn.iocoder.yudao.module.erp.service.product;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpCategorySettingPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpCategorySettingSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpCategorySettingDO;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpCategorySettingMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP 类别设定 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class ErpCategorySettingServiceImpl implements ErpCategorySettingService {

    @Resource
    private ErpCategorySettingMapper erpCategorySettingMapper;

    @Override
    public Long createCategorySetting(ErpCategorySettingSaveReqVO createReqVO) {
        // 校验父级ID的有效性
        validateParentCategorySetting(null, createReqVO.getParentId());
        // 校验名称的唯一性
        validateCategorySettingNameUnique(null, createReqVO.getParentId(), createReqVO.getName());

        // 插入
        ErpCategorySettingDO categorySetting = BeanUtils.toBean(createReqVO, ErpCategorySettingDO.class);
        erpCategorySettingMapper.insert(categorySetting);
        // 返回
        return categorySetting.getId();
    }

    @Override
    public void updateCategorySetting(ErpCategorySettingSaveReqVO updateReqVO) {
        // 校验存在
        validateCategorySettingExists(updateReqVO.getId());
        // 校验父级ID的有效性
        validateParentCategorySetting(updateReqVO.getId(), updateReqVO.getParentId());
        // 校验名称的唯一性
        validateCategorySettingNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());

        // 更新
        ErpCategorySettingDO updateObj = BeanUtils.toBean(updateReqVO, ErpCategorySettingDO.class);
        erpCategorySettingMapper.updateById(updateObj);
    }

    @Override
    public void deleteCategorySetting(Long id) {
        // 1.1 校验存在
        validateCategorySettingExists(id);
        // 1.2 校验是否有子项目
        if (erpCategorySettingMapper.selectCountByParentId(id) > 0) {
            throw exception(PRODUCT_CATEGORY_EXITS_CHILDREN);
        }
        // 2. 删除
        erpCategorySettingMapper.deleteById(id);
    }

    @Override
    public void deleteCategorySettings(Collection<Long> ids) {
        for (Long id : ids) {
            deleteCategorySetting(id);
        }
    }

    private void validateCategorySettingExists(Long id) {
        if (erpCategorySettingMapper.selectById(id) == null) {
            throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
        }
    }

    private void validateParentCategorySetting(Long id, Long parentId) {
        if (parentId == null || parentId.equals(0L)) {
            return;
        }
        // 1. 不能设置自己为父级
        if (Objects.equals(id, parentId)) {
            throw exception(PRODUCT_CATEGORY_PARENT_ERROR);
        }
        // 2. 父级不存在
        ErpCategorySettingDO parentCategory = erpCategorySettingMapper.selectById(parentId);
        if (parentCategory == null) {
            throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXITS);
        }
        // 3. 父级必须是主类别
        if (!"CATEGORY".equals(parentCategory.getType())) {
            throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXITS);
        }
    }

    private void validateCategorySettingNameUnique(Long id, Long parentId, String name) {
        ErpCategorySettingDO categorySetting = erpCategorySettingMapper.selectByParentIdAndName(parentId, name);
        if (categorySetting == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的类别设定
        if (id == null) {
            throw exception(PRODUCT_CATEGORY_NAME_DUPLICATE);
        }
        if (!Objects.equals(categorySetting.getId(), id)) {
            throw exception(PRODUCT_CATEGORY_NAME_DUPLICATE);
        }
    }

    @Override
    public ErpCategorySettingDO getCategorySetting(Long id) {
        return erpCategorySettingMapper.selectById(id);
    }

    @Override
    public PageResult<ErpCategorySettingDO> getCategorySettingPage(ErpCategorySettingPageReqVO pageReqVO) {
        return erpCategorySettingMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<ErpCategorySettingDO>()
                .eqIfPresent(ErpCategorySettingDO::getParentId, pageReqVO.getParentId())
                .likeIfPresent(ErpCategorySettingDO::getName, pageReqVO.getName())
                .eqIfPresent(ErpCategorySettingDO::getType, pageReqVO.getType())
                .eqIfPresent(ErpCategorySettingDO::getStatus, pageReqVO.getStatus())
                .orderByAsc(ErpCategorySettingDO::getSort)
                .orderByDesc(ErpCategorySettingDO::getId));
    }

    @Override
    public List<ErpCategorySettingDO> getCategorySettingList(ErpCategorySettingPageReqVO pageReqVO) {
        return erpCategorySettingMapper.selectList(pageReqVO);
    }

    @Override
    public List<ErpCategorySettingDO> getCategorySettingList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return erpCategorySettingMapper.selectList(new LambdaQueryWrapperX<ErpCategorySettingDO>()
                .in(ErpCategorySettingDO::getId, ids)
                .orderByAsc(ErpCategorySettingDO::getSort)
                .orderByDesc(ErpCategorySettingDO::getId));
    }

    @Override
    public List<ErpCategorySettingDO> getCategories() {
        return erpCategorySettingMapper.selectCategories();
    }

    @Override
    public List<ErpCategorySettingDO> getItemsByParentId(Long parentId) {
        return erpCategorySettingMapper.selectItemsByParentId(parentId);
    }

}
